'    Copyright 2008 Jan Molnar <jan.molnar@abds.de>
'
'    This file is part of JCQ.

'    JCQ is free software: you can redistribute it and/or modify
'    it under the terms of the GNU General Public License as published by
'    the Free Software Foundation, either version 2 of the License, or
'    (at your option) any later version.

'    JCQ is distributed in the hope that it will be useful,
'    but WITHOUT ANY WARRANTY; without even the implied warranty of
'    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'    GNU General Public License for more details.

'    You should have received a copy of the GNU General Public License
'    along with JCQ. If not, see <http://www.gnu.org/licenses/>.

'Public Class ContactHistoryService
'    Inherits Core.Service
'    Implements IContactHistoryService

'    Private ReadOnly _HistoryCache As New Dictionary(Of ContactViewModel, FlowDocumentReader)
'    Private Shared ReadOnly _StorageLocation As System.IO.DirectoryInfo = New System.IO.DirectoryInfo(System.IO.Path.Combine(App.DataStorageDirectoryPath, "history"))

'    Public Sub New()

'    End Sub

'    Private Shared ReadOnly Property StorageLocation() As System.IO.DirectoryInfo
'        Get
'            Return _StorageLocation
'        End Get
'    End Property

'    Public Sub Load() Implements IContactHistoryService.Load
'        Debug.WriteLine(String.Format("Loading history: {0}", StorageLocation.FullName), "Ux")

'        If Not StorageLocation.Exists Then Return

'        For Each historyFile As System.IO.FileInfo In StorageLocation.GetFiles("*.xaml")
'            Dim identifier As String
'            Dim contact As ContactViewModel

'            identifier = historyFile.Name.Substring(0, historyFile.Name.IndexOf("."))
'            contact = ContactViewModelCache.GetViewModel(ApplicationService.Current.Context.GetService(Of IcqInterface.Interfaces.IStorageService).GetContactByIdentifier(identifier))

'            Using reader As New System.Xml.XmlTextReader(historyFile.FullName)
'                Dim documentReader As FlowDocumentReader

'                documentReader = TryCast(System.Windows.Markup.XamlReader.Load(reader), FlowDocumentReader)

'                If documentReader IsNot Nothing Then
'                    _HistoryCache.Add(contact, documentReader)
'                End If
'            End Using
'        Next
'    End Sub

'    Public Sub AppendMessage(ByVal contact As ContactViewModel, ByVal message As IcqInterface.Interfaces.IMessage) Implements IContactHistoryService.AppendMessage
'        Dim reader As FlowDocumentReader
'        Dim document As FlowDocument

'        If _HistoryCache.ContainsKey(contact) Then
'            reader = _HistoryCache(contact)
'            document = reader.Document
'        Else
'            document = New FlowDocument
'            document.FontFamily = New Windows.Media.FontFamily("Calibri")

'            reader = New FlowDocumentReader
'            reader.Document = document
'            reader.Name = "reader"
'            reader.ViewingMode = FlowDocumentReaderViewingMode.Scroll

'            _HistoryCache.Add(contact, reader)
'        End If

'        Dim paragraph As Paragraph

'        'TODO: Find Sender Role
'        paragraph = Core.Kernel.Services.GetService(Of IMessageFormattingService).FormatMessage(MessageSenderRole.ContextIdentity, message)

'        document.Blocks.Add(paragraph)
'    End Sub

'    Public Sub Save() Implements IContactHistoryService.Save
'        Dim location As System.IO.DirectoryInfo

'        location = New System.IO.DirectoryInfo(System.IO.Path.Combine(App.DataStorageDirectoryPath, "history"))
'        Debug.WriteLine(String.Format("Saving history: {0}", location.FullName), "Ux")

'        If Not location.Exists Then location.Create()

'        For Each pair As KeyValuePair(Of ContactViewModel, FlowDocumentReader) In _HistoryCache
'            Dim fi As System.IO.FileInfo
'            fi = New System.IO.FileInfo(System.IO.Path.Combine(location.FullName, String.Format("{0}.xaml", pair.Key.Identifier)))

'            Using writer As New System.Xml.XmlTextWriter(fi.FullName, System.Text.Encoding.UTF8)
'                System.Windows.Markup.XamlWriter.Save(pair.Value, writer)
'            End Using
'        Next
'    End Sub

'    Public Function GetHistory(ByVal contact As ContactViewModel) As List(Of Paragraph) Implements IContactHistoryService.GetHistory
'        Dim list As New List(Of Paragraph)

'        If _HistoryCache.ContainsKey(contact) Then
'            Dim document As FlowDocument = _HistoryCache(contact).Document
'            Dim lines As String() = Core.Kernel.Services.GetService(Of IMessageFormattingService).GetTextLinesFromDocument(document)

'            For Each line As String In lines
'                Dim p As Paragraph = New Paragraph
'                Dim r As Run = New Run(line)

'                r.Foreground = Brushes.Gray

'                p.Margin = New System.Windows.Thickness(0)
'                p.Inlines.Add(r)

'                list.Add(p)
'            Next
'        End If

'        Return list
'    End Function

'    Public Function GetHistory(ByVal contact As ContactViewModel, ByVal maxItems As Integer) As List(Of Paragraph) Implements IContactHistoryService.GetHistory
'        Dim list As New List(Of Paragraph)

'        If _HistoryCache.ContainsKey(contact) Then
'            Dim document As FlowDocument = _HistoryCache(contact).Document
'            Dim lines As String() = Core.Kernel.Services.GetService(Of IMessageFormattingService).GetTextLinesFromDocument(document)

'            Dim length As Integer = lines.Length
'            Dim index As Integer = If(length > 5, length - 5, 0)

'            Do While index < length
'                Dim p As Paragraph = New Paragraph
'                Dim r As Run = New Run(lines(index))

'                r.Foreground = Brushes.Gray

'                p.Margin = New System.Windows.Thickness(0)
'                p.Inlines.Add(r)

'                list.Add(p)


'                index += 1
'            Loop
'        End If

'        Return list
'    End Function
'End Class

Public Class ContactHistoryService
    Inherits IcqInterface.ContextService
    Implements IContactHistoryService

    Private _Cache As Dictionary(Of ContactViewModel, ContactHistory)
    Private Shared ReadOnly _StorageLocation As System.IO.DirectoryInfo = New System.IO.DirectoryInfo(System.IO.Path.Combine(App.DataStorageDirectoryPath, "history"))

    Public Sub New(ByVal context As IcqInterface.Interfaces.IContext)
        MyBase.New(context)

        _Cache = New Dictionary(Of ContactViewModel, ContactHistory)
    End Sub

    Private Shared ReadOnly Property StorageLocation() As System.IO.DirectoryInfo
        Get
            Return _StorageLocation
        End Get
    End Property

    Public Sub AppendMessage(ByVal contact As ViewModel.ContactViewModel, ByVal message As ViewModel.MessageViewModel) Implements ViewModel.IContactHistoryService.AppendMessage
        Dim history As ContactHistory = Nothing

        If Not _Cache.TryGetValue(contact, history) Then
            history = New ContactHistory(contact.Model)
            _Cache.Add(contact, history)
        End If

        history.Messages.Add(message)
    End Sub

    Public Function GetHistory(ByVal contact As ViewModel.ContactViewModel) As System.Collections.Generic.List(Of ViewModel.MessageViewModel) Implements ViewModel.IContactHistoryService.GetHistory
        Dim history As ContactHistory = Nothing

        If _Cache.TryGetValue(contact, history) Then
            Return history.Messages
        Else
            Return New List(Of MessageViewModel)
        End If
    End Function

    Public Function GetHistory(ByVal contact As ViewModel.ContactViewModel, ByVal maxItems As Integer) As System.Collections.Generic.List(Of ViewModel.MessageViewModel) Implements ViewModel.IContactHistoryService.GetHistory
        Dim history As ContactHistory = Nothing
        Dim messages As List(Of MessageViewModel)

        If _Cache.TryGetValue(contact, history) Then
            messages = history.Messages

            If messages.Count > maxItems Then
                Return messages.Skip(messages.Count - maxItems).ToList
            Else
                Return messages
            End If
        Else
            Return New List(Of MessageViewModel)
        End If
    End Function

    Public Sub Load() Implements ViewModel.IContactHistoryService.Load
        Dim serializer As JCsTools.Xml.Formatter.XmlSerializer

        Debug.WriteLine(String.Format("Loading history: {0}", StorageLocation.FullName), "Ux")

        If Not StorageLocation.Exists Then Return

        serializer = New JCsTools.Xml.Formatter.XmlSerializer
        serializer.RegisterReferenceFormatter(GetType(ContactHistory), New ContactHistoryFormatter(serializer))
        serializer.RegisterReferenceFormatter(GetType(TextMessageViewModel), New TextMessageViewModelFormatter(serializer))
        serializer.RegisterReferenceFormatter(GetType(OfflineTextMessageViewModel), New OfflineTextMessageViewModelFormatter(serializer))

        For Each historyFile As System.IO.FileInfo In StorageLocation.GetFiles("*.xml")
            Dim identifier As String
            Dim contact As ContactViewModel

            identifier = historyFile.Name.Substring(0, historyFile.Name.IndexOf("."))
            contact = ContactViewModelCache.GetViewModel(ApplicationService.Current.Context.GetService(Of IcqInterface.Interfaces.IStorageService).GetContactByIdentifier(identifier))

            Using reader As New System.Xml.XmlTextReader(historyFile.FullName)
                Dim history As ContactHistory

                history = DirectCast(serializer.Deserialize(reader), ContactHistory)

                _Cache.Add(contact, history)
            End Using
        Next
    End Sub

    Public Sub Save() Implements ViewModel.IContactHistoryService.Save
        Dim fiHistoryFile As System.IO.FileInfo
        Dim serializer As JCsTools.Xml.Formatter.XmlSerializer

        Debug.WriteLine(String.Format("Saving history: {0}", StorageLocation.FullName), "Ux")

        If Not StorageLocation.Exists Then StorageLocation.Create()

        serializer = New JCsTools.Xml.Formatter.XmlSerializer
        serializer.RegisterReferenceFormatter(GetType(ContactHistory), New ContactHistoryFormatter(serializer))
        serializer.RegisterReferenceFormatter(GetType(TextMessageViewModel), New TextMessageViewModelFormatter(serializer))
        serializer.RegisterReferenceFormatter(GetType(OfflineTextMessageViewModel), New OfflineTextMessageViewModelFormatter(serializer))

        For Each pair In _Cache
            fiHistoryFile = New System.IO.FileInfo(System.IO.Path.Combine(StorageLocation.FullName, String.Format("{0}.xml", pair.Key.Identifier)))

            Using writer As New System.Xml.XmlTextWriter(fiHistoryFile.FullName, System.Text.Encoding.UTF8)
                serializer.Serialize(pair.Value, writer)
            End Using
        Next
    End Sub
End Class

Public Class ContactHistoryFormatter
    Inherits JCsTools.Xml.Formatter.DefaultIListReferenceFormatter

    Public Sub New(ByVal context As JCsTools.Xml.Formatter.ISerializer)
        MyBase.New(context, GetType(ContactHistory))
    End Sub

    Protected Overrides Function CreateObject(ByVal type As System.Type, ByVal reader As System.Xml.XmlReader) As Object
        Dim identifier As String
        Dim contact As IcqInterface.Interfaces.IContact

        identifier = reader.GetAttribute("contact")
        contact = ApplicationService.Current.Context.GetService(Of IcqInterface.Interfaces.IStorageService).GetContactByIdentifier(identifier)

        Return New ContactHistory(contact)
    End Function

    Public Overrides Sub Serialize(ByVal graph As Object, ByVal writer As System.Xml.XmlWriter)
        Dim history As ContactHistory

        history = DirectCast(graph, ContactHistory)

        writer.WriteStartElement("list")

        WriteIdAttribute(graph, writer)
        WriteTypeAttribute(graph, writer)

        writer.WriteAttributeString("contact", history.Contact.Identifier)

        SerializeItems(DirectCast(history.Messages, Collections.IList), writer)

        writer.WriteEndElement()
    End Sub

    Public Overrides Function Deserialize(ByVal reader As System.Xml.XmlReader) As Object
        Dim objectId As Integer
        Dim type As Type
        Dim history As ContactHistory

        reader.MoveToFirstAttribute() ' This is always __id
        objectId = GetObjectId(reader)

        reader.MoveToNextAttribute() ' This is always __type
        type = GetObjectType(reader)

        history = DirectCast(CreateObject(type, reader), ContactHistory)

        If Not reader.IsEmptyElement Then
            DeserializeItems(history.Messages, reader)
        End If

        Serializer.RegisterObject(objectId, history)

        Return history
    End Function
End Class

Public Class TextMessageViewModelFormatter
    Inherits JCsTools.Xml.Formatter.DefaultReferenceFormatter

    Public Sub New(ByVal parent As JCsTools.Xml.Formatter.ISerializer)
        MyBase.New(parent, GetType(TextMessageViewModel), False, False)
    End Sub

    Protected Overrides Function CreateObject(ByVal type As System.Type, ByVal reader As System.Xml.XmlReader) As Object
        Dim dateCreated As Date
        Dim senderIdentifier As String
        Dim recipientIdentifier As String
        Dim message As String

        Dim senderModel As IcqInterface.Interfaces.IContact
        Dim recipientModel As IcqInterface.Interfaces.IContact

        Dim sender As ContactViewModel
        Dim recipient As ContactViewModel

        Dim svStorage = ApplicationService.Current.Context.GetService(Of IcqInterface.Interfaces.IStorageService)()

        dateCreated = System.Xml.XmlConvert.ToDateTime(reader.GetAttribute("created"), System.Xml.XmlDateTimeSerializationMode.Utc)
        senderIdentifier = reader.GetAttribute("sender")
        recipientIdentifier = reader.GetAttribute("recipient")
        message = reader.GetAttribute("message")

        senderModel = svStorage.GetContactByIdentifier(senderIdentifier)
        recipientModel = svStorage.GetContactByIdentifier(recipientIdentifier)

        sender = ContactViewModelCache.GetViewModel(senderModel)
        recipient = ContactViewModelCache.GetViewModel(recipientModel)

        Return New TextMessageViewModel(dateCreated, sender, recipient, message, MessageColors.HistoryColor)
    End Function

    Protected Overrides Sub DeserializeProperties(ByVal graph As Object, ByVal reader As System.Xml.XmlReader)
        ' Nothing to do here
    End Sub

    Protected Overrides Sub SerializeProperties(ByVal graph As Object, ByVal writer As System.Xml.XmlWriter)
        Dim entity As TextMessageViewModel = DirectCast(graph, TextMessageViewModel)

        writer.WriteAttributeString("created", System.Xml.XmlConvert.ToString(entity.DateCreated, System.Xml.XmlDateTimeSerializationMode.Utc))
        writer.WriteAttributeString("sender", entity.Sender.Identifier)
        writer.WriteAttributeString("recipient", entity.Recipient.Identifier)
        writer.WriteAttributeString("message", entity.Message)
    End Sub
End Class

Public Class OfflineTextMessageViewModelFormatter
    Inherits JCsTools.Xml.Formatter.DefaultReferenceFormatter

    Public Sub New(ByVal parent As JCsTools.Xml.Formatter.ISerializer)
        MyBase.New(parent, GetType(OfflineTextMessageViewModel), False, False)
    End Sub

    Protected Overrides Function CreateObject(ByVal type As System.Type, ByVal reader As System.Xml.XmlReader) As Object
        Dim dateCreated As Date
        Dim dateSent As Date
        Dim senderIdentifier As String
        Dim recipientIdentifier As String
        Dim message As String

        Dim senderModel As IcqInterface.Interfaces.IContact
        Dim recipientModel As IcqInterface.Interfaces.IContact

        Dim sender As ContactViewModel
        Dim recipient As ContactViewModel

        Dim svStorage = ApplicationService.Current.Context.GetService(Of IcqInterface.Interfaces.IStorageService)()

        dateCreated = System.Xml.XmlConvert.ToDateTime(reader.GetAttribute("created"), System.Xml.XmlDateTimeSerializationMode.Utc)
        dateSent = System.Xml.XmlConvert.ToDateTime(reader.GetAttribute("sent"), System.Xml.XmlDateTimeSerializationMode.Utc)
        senderIdentifier = reader.GetAttribute("sender")
        recipientIdentifier = reader.GetAttribute("recipient")
        message = reader.GetAttribute("message")

        senderModel = svStorage.GetContactByIdentifier(senderIdentifier)
        recipientModel = svStorage.GetContactByIdentifier(recipientIdentifier)

        sender = ContactViewModelCache.GetViewModel(senderModel)
        recipient = ContactViewModelCache.GetViewModel(recipientModel)

        Return New OfflineTextMessageViewModel(dateCreated, sender, recipient, message, dateSent, MessageColors.HistoryColor)
    End Function

    Protected Overrides Sub DeserializeProperties(ByVal graph As Object, ByVal reader As System.Xml.XmlReader)
        ' Nothing to do here
    End Sub

    Protected Overrides Sub SerializeProperties(ByVal graph As Object, ByVal writer As System.Xml.XmlWriter)
        Dim entity As OfflineTextMessageViewModel = DirectCast(graph, OfflineTextMessageViewModel)

        writer.WriteAttributeString("created", System.Xml.XmlConvert.ToString(entity.DateCreated, System.Xml.XmlDateTimeSerializationMode.Utc))
        writer.WriteAttributeString("sent", System.Xml.XmlConvert.ToString(entity.DateSent, System.Xml.XmlDateTimeSerializationMode.Utc))
        writer.WriteAttributeString("sender", entity.Sender.Identifier)
        writer.WriteAttributeString("recipient", entity.Recipient.Identifier)
        writer.WriteAttributeString("message", entity.Message)
    End Sub
End Class

Public Class ContactHistory
    Private _Contact As IcqInterface.Interfaces.IContact
    Private _Messages As List(Of MessageViewModel)

    Public Sub New(ByVal contact As IcqInterface.Interfaces.IContact)
        _Contact = contact
        _Messages = New List(Of MessageViewModel)
    End Sub

    Public ReadOnly Property Contact() As IcqInterface.Interfaces.IContact
        Get
            Return _Contact
        End Get
    End Property

    Public ReadOnly Property Messages() As List(Of MessageViewModel)
        Get
            Return _Messages
        End Get
    End Property
End Class
